package com.myopen.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.Trigger.TriggerState;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.myopen.converter.ListConverter;
import com.myopen.kit.DateKit;
import com.myopen.kit.UUIDKit;


/**
 * 由于定时任务要跟当前quartz绑定，所以提供部分方法
 * @author wangsanfei
 *
 */
public class Task extends Model<Task>{

	private static final long serialVersionUID = 5617202869523721885L;
	public static final Task dao=new Task();
	
	private static SchedulerFactory schedulerFactory=new StdSchedulerFactory();
	private static Scheduler scheduler=getScheduler();
	
	
	public Page<Record> pagequery(Record record){
		StringBuffer sqlExceptSelect=new StringBuffer("from t_task t "
				+ " left join t_user u on t.creator=u.id "
				+ " where t.removed='0' ");
		List<Object> list=new ArrayList<Object>();
		
		if(StrKit.notBlank(record.getStr("searchContent"))) {
			sqlExceptSelect.append(" and t.jobName like ? ");
			list.add("%"+record.getStr("searchContent")+"%");
		}
		
		sqlExceptSelect.append(" order by t.createTime desc");
		Page<Record> page= Db.paginate(record.getInt("pageNumber"),record.getInt("pageSize"),"select t.*,u.username,u.nickname,u.email,u.cellphone ",sqlExceptSelect.toString(),list.toArray());		
		
		List<Record> records=page.getList();
		for (Record r : records) {
			
			String triggerCode=r.getStr("triggerCode");
			String triggerGroupCode=r.getStr("triggerGroupCode");
			TriggerKey triggerKey=new TriggerKey(triggerCode, triggerGroupCode);
			try {
				
				Trigger trigger=getScheduler().getTrigger(triggerKey);
				TriggerState triggerState=getScheduler().getTriggerState(triggerKey);
				r.set("triggerState", triggerState);
				if(trigger!=null) {
					r.set("nextFireTime", DateKit.format(trigger.getNextFireTime(), "yyyy-MM-dd HH:mm:ss"));
				}
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
		
		String[] dicTypeKeys= {"jobStatus"};
		String[] dicTypes= {"TASK_STATUS"};
		return new ListConverter<Record>(page,dicTypeKeys,dicTypes).getPage();
	}
	
	public List<Record> getAll(){
		String sql="select * from t_task t where t.removed='0' ";
		return Db.find(sql);
	}
	
	public Record getRecordById(String id){
		if(StrKit.isBlank(id)){
			return new Record();
		}
		String sql="select * from t_task t where t.id=? ";
		return Db.findFirst(sql,id);
	}
	
	/**
	 * 添加一个任务
	 */
	public void addTask(String jobCode,String jobGroupCode,String triggerCode,
			String triggerGroupCode,String jobName, 
			String jobClass, String jobCronExp,Record currUser) {
		try {
			
			Record bo=new Record();
			bo.set("id", UUIDKit.getUUID());
			bo.set("removed", "0");
			bo.set("createTime", new Date());
			bo.set("updateTime", new Date());
			bo.set("creator", currUser.getStr("id"));
			bo.set("updator", currUser.getStr("id"));
			bo.set("jobCode", jobCode);
			bo.set("jobGroupCode", jobGroupCode);
			bo.set("triggerCode", triggerCode);
			bo.set("triggerGroupCode", triggerGroupCode);
			bo.set("jobStatus", "TASK_STATUS_01");
			bo.set("cronExpression", jobCronExp);
			bo.set("jobName", jobName);
			bo.set("jobClass", jobClass);
			Db.save("t_task", bo);
			
			//同时注册一个任务，以方便接下来调用
			registeTask(bo);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	private CronTrigger createCronTrigger(String trigger,String triggerGroup,String jobCronExp) {
		return TriggerBuilder.newTrigger()
				.withIdentity(trigger, triggerGroup)
				.withSchedule(CronScheduleBuilder.cronSchedule(jobCronExp))
				.startNow()
				.build();
	}
	
	private JobDetail createJobDetail(String job,String jobGroup,Class<? extends Job> jobClass) {
		return JobBuilder.newJob(jobClass)
				.withIdentity(job, jobGroup)
				.build();
	}
	
	@SuppressWarnings("unchecked")
	private Class<? extends Job> createClass(String jobClass){
		try {
			return (Class<? extends Job>)Class.forName(jobClass);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 初始化一个任务调度器
	 * @return
	 */
	private static Scheduler getScheduler() {
		try {
			return schedulerFactory.getScheduler();
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 注册一个任务
	 */
	private void registeTask(Record record) {
		try {
			
			String job=record.getStr("jobCode");
			String jobGroup=record.getStr("jobGroupCode");
			String trigger=record.getStr("triggerCode");
			String triggerGroup=record.getStr("triggerGroupCode");
			String jobCronExp=record.getStr("cronExpression");
			String jobClass=record.getStr("jobClass");
			
			JobDetail jobDetail = createJobDetail(job,jobGroup,createClass(jobClass));
			CronTrigger cronTrigger=createCronTrigger(trigger,triggerGroup,jobCronExp);
			scheduler.scheduleJob(jobDetail, cronTrigger);
			
			if("TASK_STATUS_01".equals(record.getStr("jobStatus"))) {
				//如果是停止状态下，取消执行
				JobKey jobKey=new JobKey(job, jobGroup);
				scheduler.pauseJob(jobKey);
			}
			
		} catch (Exception e) {
			
			//此处更新数据库信息
			record.set("jobStatus", "TASK_STATUS_99");//设置启动失败
			record.set("errInfo", "该任务初始化失败");//
			Db.update("t_task", record);
			
			e.printStackTrace();
		}
	}
	
	/**
	 * 初始化所有任务
	 */
	public String initAllTask() {
		//查询处，正在执行和暂停中的任务
		String sql="select * from t_task t where t.removed='0' ";
		List<Record> tasks=Db.find(sql);
		for (Record record : tasks) {
			registeTask(record);
		}
		
		try {
			scheduler.start();
		} catch (SchedulerException e) {
			for (Record record : tasks) {
				record.set("jobStatus", "TASK_STATUS_99");//设置启动失败
				record.set("errInfo", "该任务初始化失败");//
				Db.update("t_task", record);
			}
			e.printStackTrace();
		}
		
		return "0";
		
	}
	
	
	
	
	
	/**
	 * 暂停一个任务
	 */
	public String pauseTask(String id) {
		Record task=Db.findById("t_task", id);
		String job=task.getStr("jobCode");
		String jobGroup=task.getStr("jobGroupCode");
		
		JobKey jobKey=new JobKey(job, jobGroup);
		try {
			
			scheduler.pauseJob(jobKey);
			
			String triggerCode=task.getStr("triggerCode");
			String triggerGroupCode=task.getStr("triggerGroupCode");
			TriggerKey triggerKey=new TriggerKey(triggerCode, triggerGroupCode);
			TriggerState triggerState=getScheduler().getTriggerState(triggerKey);
			if(triggerState!=TriggerState.NONE) {
				//如果含有该项job才进行更新
				task.set("jobStatus", "TASK_STATUS_01");
				Db.update("t_task",task);
			}
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		
		return "0";
	}
	
	/**
	 * 运行一个任务
	 */
	public String resumeTask(String id) {
		
		Record task=Db.findById("t_task", id);
		String job=task.getStr("jobCode");
		String jobGroup=task.getStr("jobGroupCode");
		
		JobKey jobKey=new JobKey(job, jobGroup);
		try {
			
			scheduler.resumeJob(jobKey);
			
			String triggerCode=task.getStr("triggerCode");
			String triggerGroupCode=task.getStr("triggerGroupCode");
			TriggerKey triggerKey=new TriggerKey(triggerCode, triggerGroupCode);
			TriggerState triggerState=getScheduler().getTriggerState(triggerKey);
			if(triggerState!=TriggerState.NONE) {
				//如果含有该项job才进行更新
				task.set("jobStatus", "TASK_STATUS_00");
				Db.update("t_task",task);
			}
			
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		
		return "0";
	}
	
	/**
	 * 删除一个任务
	 */
	public String deleteTask(String id) {
		
		Record task=Db.findById("t_task", id);
		String job=task.getStr("jobCode");
		String jobGroup=task.getStr("jobGroupCode");
		
		JobKey jobKey=new JobKey(job, jobGroup);
		try {
			scheduler.deleteJob(jobKey);
			
			Db.deleteById("t_task", id);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		
		return "0";
	}
	
	/**
	 * 立刻执行一次任务
	 */
	public String runATask(String id) {
		
		Record task=Db.findById("t_task", id);
		String job=task.getStr("jobCode");
		String jobGroup=task.getStr("jobGroupCode");
		
		JobKey jobKey=new JobKey(job, jobGroup);
		try {
			scheduler.triggerJob(jobKey);
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
		
		return "0";
	}
	
}
